home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Game-Power
/
Amiga Game-Power.iso
/
pd mix ii
/
rot
/
heliosmouse
/
heliosmouse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-20
|
9KB
|
281 lines
/*
* HeliosMouse.c Installs an input handler that activates windows when
* you move the mouse over inactive ones.
*
* Copyright (c) 1987 by Davide P. Cervone
* You may use this code provided this copyright notice is left intact.
*/
#include <exec/types.h>
#include <libraries/dos.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
static char *program = "HeliosMouse";
static char *version = "v1.0";
static char *date = "June 1987";
static char *author = "Copyright (c) 1987 by Davide P. Cervone";
static char *PortName = "HeliosPort";
static char *handler = "L:Helios-Handler"; /* the handler file */
#define HANDLER &(handler[2]) /* without the "L:" */
/*
* This is the structure that holds the handler information between calls
* to HeliosMouse. We create a named, public message-port that points to
* an instance of this structure so that we can find this information
* when we are asked to remove the handler. The PortName is stored here
* (NamedPort->mp_Node.ln_Name uses this area for its name). The other
* data are what we need in order to remove the handler and clean up properly.
*/
struct HandlerBlock
{
char *PortName; /* name of the public, named message-port */
struct Interrupt Handler; /* the handler added to the handler chain */
struct IntuitionBase *Ibase; /* library base used by the handler */
struct LayersBase *Lbase; /* library base used by the handler */
long Segment; /* pointer from LoadSeg() */
};
#define HANDLERINFOSIZE sizeof(struct HandlerBlock)
#define NAMESIZE (strlen(PortName)+1)
extern struct MsgPort *CreatePort();
extern struct IOStdReq *CreateStdIO();
extern struct MsgPort *FindPort(), *CreatePort();
extern APTR AllocMem();
extern long LoadSeg();
#define INTUITION_REV 0L
#define LAYERS_REV 0L
struct IntuitionBase *IntuitionBase = NULL;
struct LayersBase *LayersBase = NULL;
extern struct SysBase *SysBase;
struct MsgPort *InputPort = NULL; /* Port used to talk to Input.Device */
struct IOStdReq *InputBlock = NULL; /* request block used with Input.Device */
LONG InputDevice = 0; /* flag whether Input.Device is open */
struct MsgPort *NamedPort = NULL; /* holds info needed to remove handler */
struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
/*
* DoExit()
*
* General purpose exit routine. If 's' is not NULL, then print an
* error message with up to three parameters. Free any memory, close
* any open device, delete any ports, close any libraries, etc.
*/
void DoExit(s,x1,x2,x3)
char *s, *x1, *x2, *x3;
{
long status = RETURN_OK;
if (s != NULL)
{
printf(s,x1,x2,x3);
printf("\n");
status = RETURN_ERROR;
}
if (InputDevice) CloseDevice(InputBlock);
if (InputBlock) DeleteStdIO(InputBlock);
if (InputPort) DeletePort(InputPort);
if (NamedPort) DeletePort(NamedPort);
if (HandlerInfo)
{
if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
FreeMem(HandlerInfo,HANDLERINFOSIZE);
}
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (LayersBase) CloseLibrary(LayersBase);
exit(status);
}
/*
* CheckLibOpen()
*
* General library open routine. It opens a library and sets a pointer
* to it. It checks that the library was openned successfully.
*/
void CheckLibOpen(lib,name,rev)
APTR *lib;
char *name;
int rev;
{
extern APTR OpenLibrary();
if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
DoExit("Can't open '%s'\n",name);
}
/*
* Macros that make memory allocation easier.
*/
#define NEW(s,var) (var = (struct s *)New("var",sizeof(struct s)))
#define NEWCHAR(var,s) (var = (char *)New("var",s))
/*
* New()
*
* Allocate public memory of a given size and set it to all zeros. If there
* is not enough memory, then exit with an error, otherwise return the
* pointer to the newly allocated memory.
*/
APTR New(name,size)
char *name;
int size;
{
APTR ptr;
if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
DoExit("Can't Get Memory for '%s'");
return(ptr);
}
/*
* TellInputDevice()
*
* Create a port and I/O block, and open the input device. Set up the
* I/O block to add or remove the input handler, and send the request
* to the input device. Finally, close the device and delete the
* I/O block and port.
*/
void TellInputDevice(function)
int function;
{
long status;
if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
if ((InputBlock = CreateStdIO(InputPort)) == NULL)
DoExit("Can't Create Standard IO Block");
InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
InputBlock->io_Command = (long) function;
InputBlock->io_Data = (APTR) &(HandlerInfo->Handler);
if (status = DoIO(InputBlock)) DoExit("Error from DoIO: %ld",status);
CloseDevice(InputBlock);
DeleteStdIO(InputBlock);
DeletePort(InputPort);
}
/*
* CreateHandler()
*
* Open the libraries needed by the input handler and store their locations
* in the HandlerInfo structure (so we can close them later). Try to
* LoadSeg() the handler. If it is not in the current directory, try the
* L: directory. Exit with an error if the handler can't be found.
* Convert the segment pointer into a pointer to the Setup routine (the
* first routine in the handler executable). Call Setup() and pass it
* the pointers to the libraries that it will need to use. Setup() returns
* a pointer to the actual handler routine that should be added into the
* input handler chain. Store this in the HandlerInfo structure so we
* can use it to remove the handler later. Set the handler priority to
* 51 so that it is ahead of Intuition.
*
* Finally, add the handler in the chain and tell the user that the
* handler has been installed.
*/
void CreateHandler()
{
long (*Setup)();
CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
HandlerInfo->Ibase = IntuitionBase;
HandlerInfo->Lbase = LayersBase;
if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
DoExit("Can't Load '%s'",handler);
Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
HandlerInfo->Handler.is_Code =
(void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase));
HandlerInfo->Handler.is_Node.ln_Pri = 51;
TellInputDevice(IND_ADDHANDLER);
printf("%s %s (%s) Installed\n",program,version,date);
}
/*
* Delete Handler()
*
* Retreive the library pointers from the HandlerInfo structure where
* we stored them when we originally installed the handler, then remove
* the handler from the input handler chain. Tell the user that the
* handler is gone and then close the libraries that are no longer needed.
*/
void DeleteHandler()
{
IntuitionBase = HandlerInfo->Ibase;
LayersBase = HandlerInfo->Lbase;
TellInputDevice(IND_REMHANDLER);
UnLoadSeg(HandlerInfo->Segment);
printf("%s Removed\n",program);
CloseLibrary(IntuitionBase);
CloseLibrary(LayersBase);
}
/*
* main()
*
* Check if a message port with our name already exists.
* If not, then the handler is not already installed, so:
* Allocate a new HandlerInfo structure and initialize the port name.
* Create a public, names message-port (we will look for this the next
* time HeliosMouse is called).
* Make the message port point to the HandlerInfo structure so we
* can use it later when the user asks us to remove the handler.
* Note that the port is not actually used for putting and getting
* messages, so the Task field is never used, so we can take it for
* our own uses.
* Finally, add the input handler into the chain.
* Otherwise, the port exists, so HeliosMouse already is installed:
* Retreive the HandlerInfo poiner from the port, and
* remove the handler from the input handler chain.
* Free the memory used by the HandlerInfo, and delete the message port.
*/
void main()
{
NamedPort = FindPort(PortName);
if (NamedPort == NULL)
{
NEW(HandlerBlock,HandlerInfo);
NEWCHAR(HandlerInfo->PortName,NAMESIZE);
strcpy(HandlerInfo->PortName,PortName);
if ((NamedPort = CreatePort(HandlerInfo->PortName,0)) == NULL)
DoExit("Can't Create Message Port '%s'",PortName);
NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
CreateHandler();
} else {
HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
DeleteHandler();
FreeMem(HandlerInfo->PortName,NAMESIZE);
FreeMem(HandlerInfo,HANDLERINFOSIZE);
DeletePort(NamedPort);
}
}